package com.bq.server.utils;


import cn.hutool.core.util.ArrayUtil;
import com.google.common.collect.Maps;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.Objects;
import java.util.concurrent.ConcurrentMap;

/**
 * 编码工具类
 * 实现aes加密、解密
 */
public class EncryptUtils {

    private static final ConcurrentMap<String, SecretKeySpec> keyCache = Maps.newConcurrentMap();

    /**
     * 算法
     */
    private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";

    private static final String AES = "AES";


    /**
     * 默认加密key
     */
    public static final String DEFAULT_ENCRYPT_KEY = "3nQix#abiXAoV4Io";

    /**
     * AES加密
     * @param content 待加密的内容
     * @param encryptKey 加密密钥
     * @return 加密后的byte[]
     */
    public static byte[] aesEncryptToBytes(String content, String encryptKey) throws GeneralSecurityException {
        if (StringUtils.isEmpty(content)) {
            return null;
        }
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        cipher.init(Cipher.ENCRYPT_MODE, getSecretKeySpec(encryptKey));
        return cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
    }

    public static String aesEncrypt(String content) throws GeneralSecurityException {
        return aesEncrypt(content, DEFAULT_ENCRYPT_KEY);
    }

    /**
     * AES加密为base 64 code
     * @param content 待加密的内容
     * @param encryptKey 加密密钥
     * @return 加密后的base 64 code
     */
    public static String aesEncrypt(String content, String encryptKey) throws GeneralSecurityException {
        return Base64Utils.encodeToString(Objects.requireNonNull(aesEncryptToBytes(content, encryptKey)));
    }

    /**
     * AES解密
     * @param encryptBytes 待解密的byte[]
     * @param decryptKey 解密密钥
     * @return 解密后的String
     */
    public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws GeneralSecurityException {
        if (ArrayUtil.isEmpty(encryptBytes)) {
            return null;
        }
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
        cipher.init(Cipher.DECRYPT_MODE, getSecretKeySpec(decryptKey));
        byte[] decryptBytes = cipher.doFinal(encryptBytes);

        return new String(decryptBytes, StandardCharsets.UTF_8);
    }

    public static String aesDecrypt(String content) throws GeneralSecurityException {
        return aesDecrypt(content, DEFAULT_ENCRYPT_KEY);
    }

    /**
     * 将base 64 code AES解密
     * @param encryptStr 待解密的base 64 code
     * @param decryptKey 解密密钥
     * @return 解密后的string
     */
    public static String aesDecrypt(String encryptStr, String decryptKey) throws GeneralSecurityException {
        return aesDecryptByBytes(Base64Utils.decodeFromString(encryptStr), decryptKey);
    }

    private static SecretKeySpec getSecretKeySpec(String key) {
        return keyCache.computeIfAbsent(key, s ->
                new SecretKeySpec(s.getBytes(StandardCharsets.UTF_8), AES));
    }

}  

